链接:点击打开链接
题意:给出一个h*w的图形,将一些字母组成的图片重叠在一起,输出所有的可能
代码:
#include <set>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
int N,M,cnt;
int vis[505],que[505];
int head[505],indegree[505];
char c[105],s[105][105];
struct node{
int to,next;
}G[505];
void addedge(int u,int v){
G[cnt].to=v;
G[cnt].next=head[u];
head[u]=cnt++;
}
void dfs(int sum){
int i,j;
if(sum==N){
for(i=0;i<N;i++)
printf("%c",c[que[i]]);
printf("\n");
return ;
}
for(i=1;i<=N;i++){
if(indegree[i]==0&&vis[i]==0){
vis[i]=1;
que[sum]=i;
for(j=head[i];j!=-1;j=G[j].next)
indegree[G[j].to]--;
dfs(sum+1);
vis[i]=0;
for(j=head[i];j!=-1;j=G[j].next)
indegree[G[j].to]++;
}
}
} //输出所有拓扑序
struct edge{
int l1,r1,l2,r2;
}tmp[505];
int main(){
int i,j,p,q,k,h,w,sign;
while(scanf("%d%d",&h,&w)!=EOF){
cnt=0;
set<char> se;
set<char>::iterator ite;
memset(vis,0,sizeof(vis));
memset(head,-1,sizeof(head));
memset(indegree,0,sizeof(indegree));
for(i=1;i<=h;i++)
for(j=1;j<=w;j++){
scanf(" %c",&s[i][j]);
if(s[i][j]>='A'&&s[i][j]<='Z')
se.insert(s[i][j]);
}
k=1;
for(ite=se.begin();ite!=se.end();ite++){
tmp[k].l1=tmp[k].r1=INF;
tmp[k].l2=tmp[k].r2=0;
c[k++]=*ite;
} //找出所有的字母
N=se.size();
for(i=1;i<=h;i++)
for(j=1;j<=w;j++){
for(k=1;k<=N;k++){
if(s[i][j]==c[k]){
tmp[k].l1=min(tmp[k].l1,i);
tmp[k].r1=min(tmp[k].r1,j);
tmp[k].l2=max(tmp[k].l2,i);
tmp[k].r2=max(tmp[k].r2,j);
}
}
} //求出所有相框的左上角和右上角
for(i=1;i<=N;i++){
for(j=1;j<=N;j++){
if(i!=j){ //找出每张图片的可能重叠情况并建图
for(q=tmp[i].r1;q<=tmp[i].r2;q++)
if(s[tmp[i].l1][q]==c[j]){
addedge(i,j);
indegree[j]++;
goto next;
}
for(q=tmp[i].r1;q<=tmp[i].r2;q++)
if(s[tmp[i].l2][q]==c[j]){
addedge(i,j);
indegree[j]++;
goto next;
}
for(q=tmp[i].l1;q<=tmp[i].l2;q++)
if(s[q][tmp[i].r1]==c[j]){
addedge(i,j);
indegree[j]++;
goto next;
}
for(q=tmp[i].l1;q<=tmp[i].l2;q++)
if(s[q][tmp[i].r2]==c[j]){
addedge(i,j);
indegree[j]++;
goto next;
}
}
next:;
}
}
dfs(0);
}
return 0;
}